|
* 68000 assembly language program
* -------------------------------
*
* Priciples of Computers2 ICA
*
* To emulate a simple 4 function calculator including
* the functions +,-,/,*
* The program must handle integers in the range 0-999.
*
* -----------------------------------------------------------------------
ORG $400
;Store program from location 400h
BSR john
;version
begin BSR
erase
;clean all storage space in memory
BSR messg
;show the startup message
BSR clean
;clean up all scratch space areas
BSR input1
;get the first sequence of no.s
BSR saven1
;save the sequence as number
CMP #1,D5
;was the last char an integer?
BNE sopsub
;if not then branch and save the char(poss an 'op')
BSR clean
;clean up all scratch space areas
BSR chget
;get a single char from the std/io
BSR store
;save the char
BSR getop
;now see if the char was indeed an operator
sopsub BSR
saveop
;if it was, then save it in memory('op')
CMP #1,D6
;if this is set, then there was an error
BEQ begin
;if another integer was input, then error - restart
BSR clean
;clean up all scratch space areas
BSR input1
;get the second sequence of integers
BSR saven2
;save the sequence as number2
CMP #6,D5
;was the last char an equals?
BEQ final
;if yes, then goto final processing
BSR clean
;else clean up all scratch space areas
BSR getequ
;and now get the equals char
BSR clean
;clean up all scratch space areas
final BSR
do_opp
;performs the calculation
CMP #1,D5
;did the divide 'op' print out its result?
BEQ cleanup
;if yes, then skip to the prompt
BSR clean
;cleanup
BSR output
;else output result
cleanup BSR clean
;cleanup
BSR newline
;insert a blank line - prettiness only
BSR goagain
;do we want to go again?
CMP #$20,D1
;if space is pressed, then yes.
BEQ begin
;now back to beginning of code
exit
STOP #$2700
;else stop the program
ORG $1000
;Start storing data at location 1000h
valid CMP
#llimit,D4 ;Compare
temp area with lower limit(0)
BLT bex
;If less than 0 then go to 'bex' (before 'ex')
CMP #ulimit,D4
;Compare temp area with upper limit(9)
BGT bex
;If greater than 9 then go to 'bex' (before 'ex')
MOVE.B #1,D5
;Set D5 to 1 - ie, number is between 0-9
BRA ex
;Branch to 'ex' and therefore miss clearing D5
bex
BRA getop
;if its not a 'int' - is it an 'op'
ex
RTS
;Return to place from where called
input1
ADDQ #1,D2
;start a counter - use quick add
BSR chget
;get a single char
BSR store
;store char in d4
BSR valid
;is d4-char valid?
CMP #1,D5
;is d5 = 1?
BNE endinpb
;if not then exit
bsrch BSR
change
;change char to integer
CMP #0,D7
;is anything in d7?
BEQ firstad
;if not then goto firstadd
add_mul MOVE.B #0,D5
;clear d5
MOVE.B D7,D3
;make a copy of D7 in D3.
MULU #10,D3
;multiply copy by 10
CMP #max,D3
;is copy >= 1000?
BGE add_ext
;if yes then exit
MULU #10,D7
;else multiply D7 by 10
ADD.W D4,D7
;now add D5 to D7.
MOVE.B #1,D5
;set d5 to 1
add_ext CMP #1,D5
;was addmul successful?
BNE endinpb
;if not then end input routine
BRA endinpa
;else goto end of loop
firstad MOVE.B D4,D7
;move D4 to D7
CMP #3,D2
;is the count up to 3 yet?
BEQ endinpb
;if yes then exit
endinpa BRA
input1
;back to beginning of loop
endinpb RTS
getop CMP
#43,D4
;is the char a '+'?
BEQ ad
;yes
CMP #45,D4
;no; is the char a '-'?
BEQ min
;yes
CMP #47,D4
;no; is the char a '/'?
BEQ divi
;yes
CMP #42,D4
;no; is the char a '*'?
BEQ mult
;yes
CMP #$3D,D4
;no; is it a '='?
BEQ equ
;yes
CMP #$D,D4
;treat return as '='
BEQ equ
;If so, then branch to equals routine
CMP #bhelp,D4
;was the HELP key pressed?
BEQ helpdsp
;if so, then display help
CMP #lhelp,D4
;was the help key pressed?
BEQ helpdsp
;if so, then display help
CMP #bcred,D4
;was the CREDITS key pressed?
BEQ credits
;if so, then display credits
CMP #lcred,D4
;was the credits key pressed?
BEQ credits
;if so, then display credits
MOVE.B #0,D5
;set D5 to 1 if no 'op' (eg 'int')
BSR newline
;- char was neither an 'int' nor an
BSR oedisp
;- and 'op' so output an error message
BSR display
;-
BSR newline
;-
BRA op_ex
;now exit the subprogram
equ
MOVE.B #6,D5
;set the level of d5 to 6
BRA op_ex
;exit subprogram
mult
MOVE.B #2,D5
;set the level of d5 to 2
BRA op_ex
;exit subprogram
divi
MOVE.B #3,D5
;set the level of d5 to 3
BRA op_ex
;exit subprogram
min
MOVE.B #4,D5
;set the level of d5 to 4
BRA op_ex
;exit subprogram
ad
MOVE.B #5,D5
;set the level of d5 to 5
op_ex RTS
;exit subprogram
do_opp MOVE.B op,D5
;move the 'op' level to D5
CMP #2,D5
;- find out what 'level' D5 is at, and
BEQ op_mult
;- then branch to the particular
CMP #5,D5
;- subprogram that corresponds to that
BEQ op_add
;- operation. eg level '3' = divide
CMP #3,D5
;-
BEQ op_div
;-
CMP #4,D5
;-
BEQ op_min
;-
CMP #1,D5
;level 1 or below is not an operator so
BLE errout
;print out an error message.
ds_exit RTS
;exit subprogram
op_mult MOVE.W number2,D7
;- This is a simple routine for
MOVE.W number1,D6
;- multiplying two 16bit integers, the
MULS.W D6,D7
;- 32bit result is in D7, and is stored
MOVE.L D7,result
;- in memory as 'result'
RTS
;exit subprogram
setof MOVE.B
#1,overflow
RTS
op_div BSR clean
;make sure all the scratch areas are clear
MOVE.W number2,D7
;number2
MOVE.W number1,D4
;make a copy of number 1 in D4
MOVE.W number1,D6
;number1
CMP D6,D7
;is number2 bigger than number1
BGT noloops
;if yes then exit
subloop ADDQ #1,D2
;add 1 to division count
SUB.W D7,D4
;subtract number2 from D4
CMP D7,D4
;is remainder > original?
BLT endloop
;if yes then exit
BRA subloop
;and go back to subloop
noloops MOVE.L #0,result
;set result to 0 (its less than 1)
BSR divdisp
;call the 'less than 1' message
BSR display
;display the message
BSR newline
;put in another newline.
MOVE.B #1,D5
;we will need this to we have displayed lessthan1
BRA enddiv
endloop MOVE.L D2,result
;move the number of loops to result
enddiv RTS
;the number of loops is number1/number2
op_min MOVE.W number1,D7
;- This subprogram takes number1 and
MOVE.W number2,D6
;- number2 and performs a subtraction
CMP.W D7,D6
;compare number1 and number2
BGE subtr
;is number2 larger?
MOVE.W number1,D6
;if yes then swap
MOVE.W number2,D7
;
MOVE.B #1,flag
;set negative flag to true
subtra SUB.W D6,D7
;perform subtraction
MOVE.L D7,result
;store result in memory
RTS
;exit subprogram
op_add MOVE.W number2,D7
;- This routine performs an addition
MOVE.W number1,D6
;- operation on the two numbers, and
ADD.W D6,D7
;- then places the new number in result
MOVE.L D7,result
;-
RTS
;exit subprogram
store MOVE.B
D1,D4
;store d1 in d4
RTS
change SUB #48,D4
;subtract 48 from ascii value of d4
RTS
getequ BSR chget
;get a char from the std/io
BSR store
;store in D4
BSR valid
;is the char valid?
CMP #0,D5
;0 signifies not valid
BEQ equ_ext
;branch to exit
BRA getequ
;back to start of loop
equ_ext RTS
;exit subprogram
clean CLR.L
D0
;- This subprogram cleans up all
CLR.L D1
;- scratch space areas
CLR.L D2
;-
CLR.L D3
;-
CLR.L D4
;-
CLR.L D5
;-
CLR.L D6
;-
CLR.L D7
;-
RTS
erase MOVE.L
#0,result
;- Reset all memory locations which
MOVE.W #0,number1
;- are used to hold data for
MOVE.W #0,number2
;- calculations
MOVE.B #0,flag
;-
MOVE.B #0,op
;-
RTS
chget MOVE.B #5,D0
;Gets a character from the keyboard
TRAP #15
;stores the ascii value in D1
RTS
;Back to the routine from where it was called.
chput MOVE.B #6,D0
;Gets a character from D1, and outputs
TRAP #15
;it to the screen
RTS
;Back to the routine from where it was called.
newlin MOVE.B #$D,D1
;Put the newline character in D1
BSR chput
;Output D1 to the screen
RTS
saven1 MOVE.W D7,number1
;save result of processing in 'number1'
RTS
;exit subprogram
saven2 MOVE.W D7,number2
;save result of processing in 'number2'
RTS
;exit subprogram
saveop CMP #43,D4
;is the char a '+'?
BEQ save
;then save
CMP #45,D4
;is the char a '-'?
BEQ save
;then save
CMP #47,D4
;is the char a '/'?
BEQ save
;then save
CMP #42,D4
;is the char a '*'?
BEQ save
;then save
BSR newline
;put in a newline
BSR nedisp
;if not a 'op' then you've tried to go over 999
BSR display
;display the numerical error message.
BSR newline
;put in a newline
BSR rsdisp
;ask to re-input data
BSR display
;display the message
MOVE.B #1,D6
;set d6
BRA endsave
;end the save routine
save
MOVE.B D5,op
;save the level of the operator in 'op'
endsave RTS
;exit subprogram
stord7 MOVE.L D7,D6
;make a copy of result
RTS
negoutp MOVE.B #'-',D1
;put a '-' in the output stream
BSR chput
;call the single ch display routine
RTS
output BSR clean
;clean up all scratch areas
MOVE.B #6,D2
;set the count to 6(places)
MOVE.L result,D7
;copy result into a register
MOVE.L result,D5
;a copy in d5 for reference
MOVE.W #maxmult,D4
;make a copy of highest 16bit integer in D4
CMP.L D4,D7
;did a multiplication result in a >16bit result?
BLE loopstka
;if not, then goto loop
BSR ofsub
;put pointer to error in A0
BSR display
;display error message
BRA exoutp
;exit subprogram
loopstka CMP #1,flag
;is negative flag set?
BEQ negoutp
;yes then output '-'
loopstk CMP #0,D2
;is count = 0?
BEQ exloop
;if yes, then exit loop
*
MOVE.L D6,D7
;- These are 68020 instructions....pity, they
*
DIVSL.L #10,D7:D6
;- would have let me use 999*999 :-(
DIVU #10,D7
;divide the result by 10 - gets lsb
SWAP D7
;swap remainder and whole number words around
MOVE.B D7,-(SP)
;store integer on the stack (f.i.l.o)
SWAP D7
;get the whole number back
AND.L #$0000FFFF,D7 ;get
rid of the remainder
SUB #1,D2
;decrement the loop counter
BRA loopstk
;back to loop
exloop MOVE.B #6,D2
;set up the counter again
loopout CMP #0,D2
;is counter = 0?
BEQ exoutp
;if yes, then exit
MOVE.B (SP)+,D1
;get integer from stack, and increment stack pointer
SUB #1,D2
;decrement the counter
CMP #0,D1
;is the number a zero?
BNE setflag
;if not, then set the print flag
backher CMP #1,D3
;is print flag set?
BEQ addline
;if yes then continue
BRA loopout
;else back to loop
addline ADD.B #$30,D1
;re-encode the integer as an ascii char
CMP #1,D3
;is the flag set?
BNE loopout
;if not then back to loop
MOVE.B #6,D0
;- else get a char from D1, and outputs
TRAP #15
;- it to the screen
BRA loopout
;back to the loop
zeroout MOVE.B #$30,D1
;if result is a zero - simply output a zero
BSR chput
;ouput single char
BRA exoutp
;goto exit
setflag MOVE.B #1,D3
;if the number is non-zero, then set the display flag
BRA backher
;go back to place from where called
exoutp RTS
;exit subprogram
display MOVE.B (A0)+,D1
;- This is a generic display function.
CMP.B #'@',D1
;- A pointer to the text string is placed
BEQ dis_ext
;- on A0 and the string traversed (A0)+
BSR chput
;- , copied to D1 and ouput by the 'chput'
BRA display
;- routine.
dis_ext RTS
;exit subprogram
messg BSR
newline
;- This section of code displays the
LEA messg1,A0
;- program banner that is shown when-
BSR display
;- -ever the user is prompted to input
BSR newline
;- a new sum.
LEA messg3,A0
;- The generic display routine is called
BSR display
;- to output the string pointed at by A0.
BSR newline
;-
RTS
;exit subprogram
goagain
BSR newline
;- A simple subprogram to display a
LEA again,A0
;- message asking whether the user
BSR display
;- would like to continue or not.
BSR newline
;- The test is in the main body.
BSR chget
;-
RTS
;exit subprogram
space LEA
addspc,A0
;adds a space to the output if needed.
RTS
;exit subprogram
newline MOVE.B #$0A,D1
;- A new line is inserted and the
BSR chput
;- cursor returned to the start of the
MOVE.B #$0D,D1
;- new line with this code - used mainly
BSR chput
;- for tidiness of output.
RTS
;exit subprogram
nedisp LEA
numerr,A0
;pointer for numerr placed on A0
RTS
;exit subprogram
oedisp LEA
operr,A0
;pointer for operr placed on A0
RTS
;exit subprogram
rsdisp LEA
restart,A0
;pointer to restart message placed on A0
RTS
;exit subprogram
errout BSR
oedisp
;- a combination of operror and the
BSR display
;- display function, used in do_opp.
RTS
;exit subprogram
divdisp LEA diverr,A0
;a message when divide result is < 1
RTS
;exit subprogram
helpdsp BSR newline
;- This rather large subprogram calls in
LEA help1,A0
;- turn the display routine on several,
BSR display
;- large test strings in memory.
BSR newline
;- These strings contain some useful info
LEA help2,A0
;- about the program and its functions...
BSR display
;- This help text is called by pressing
BSR newline
;- the 'h' key while the program is
LEA help3,A0
;- running.
BSR display
BSR newline
LEA help4,A0
BSR display
BSR newline
LEA help5,A0
BSR display
BSR newline
LEA help6,A0
BSR display
BSR newline
LEA help2,A0
BSR display
BSR newline
LEA help7,A0
BSR display
BSR newline
LEA help8,A0
BSR display
BSR newline
LEA help9,A0
BSR display
BSR newline
LEA help2,A0
BSR display
BSR newline
BSR newline
BSR newline
BSR newline
BSR newline
BSR newline
BSR newline
BSR newline
BSR newline
BSR newline
BSR newline
BSR newline
RTS
;exit subprogram
credits
BSR newline
;- This subprogram just shows some nice
LEA help19,A0
;- details and sources of information
BSR display
;- that I used.
BSR newline
LEA help2,A0
BSR display
BSR newline
LEA help10,A0
BSR display
BSR newline
LEA help11,A0
BSR display
BSR newline
LEA help12,A0
BSR display
BSR newline
LEA help13,A0
BSR display
BSR newline
LEA help14,A0
BSR display
BSR newline
BSR newline
LEA help15,A0
BSR display
BSR newline
LEA help16,A0
BSR display
BSR newline
LEA help17,A0
BSR display
BSR newline
LEA help18,A0
BSR display
BSR newline
BSR newline
LEA help21,A0
BSR display
BSR newline
LEA help22,A0
BSR display
BSR newline
LEA help23,A0
BSR display
BSR newline
LEA help24,A0
BSR display
BSR newline
LEA help2,A0
BSR display
BSR newline
BSR newline
BSR newline
BSR newline
BSR newline
RTS
john
LEA johntxt,A0
;- Prints out the program title
BSR display
;- and current version.
BSR newline
;a newline for tidiness
RTS
;exit subprogram
ofsub
LEA ofmessg,A0
RTS
********************************************************
* Define some constants
*
llimit EQU 48
;The lower limit for an ascii char is x
ulimit EQU 57
;The upper limit for an ascii char is y
max EQU
1000
;when we should stop adding.
return EQU $D
;ascii value of return ' '.
equal EQU $3D
;ascii value of equals '='.
bhelp EQU $48
;ascii value of 'H'
lhelp EQU $68
;ascii value of 'h'
bcred EQU $43
;ascii value of 'C'
lcred EQU $63
;ascii value of 'c'
zero EQU 0
;
int EQU
1
;
maxmult EQU 65535
;max result for 16bit integer
maxres EQU 998001
;999x999
halfand EQU %00000000000000001111111111111111
*
********************************************************
* This is what the value of d5 represents
*
integer EQU 1
multi EQU 2
divide EQU 3
minus EQU 4
adding EQU 5
equals EQU 6
none EQU 0
*
********************************************************
* A help banner
*
help1 DC.B ' Calculator
help text v1.1 @',0
help2 DC.B ' ---------------------------------------------------
@',0
help3 DC.B ' This program
simulates a simple 4 function numeric calculator.@',0
help4 DC.B ' You are allowed
to use integers up to and including 999, only basic functions@',0
help5 DC.B ' are implemented.@',0
help6 DC.B ' Operators
allowed are plus(+), minus(-), multiplication(*) and division(/).@',0
help7 DC.B ' Limitations.@',0
help8 DC.B ' * Negatives
are not supported.@',0
help9 DC.B ' * Division
only gives integer values.@',0
help10 DC.B ' Development tools
used.@',0
help11 DC.B ' * Teesside University
68K cross assembler@',0
help12 DC.B ' * Teesside University
68K simulator@',0
help13 DC.B ' * BSVC-2.0 68000
simulator studio (Linux)@',0
help14 DC.B ' * DOSemu v0.66.7
for iNTEL Linux@',0
help15 DC.B ' Enhancements over
standard ICA.@',0
help16 DC.B ' * Extensive handling
of input errors@',0
help17 DC.B ' * Results handled
OVER 65535 (16bit)@',0
help18 DC.B ' * Non-output of
overflowed results@',0
help19 DC.B ' Calculator credits
and data text v1.0@',0
help20 DC.B ' * General improvement
in user interface@',0
help21 DC.B ' Sources of information,
and thanks.@',0
help22 DC.B ' * A.Clements
68000 Family assembly language@',0
help23 DC.B ' * A.Clements
Microprocessor systems design@',0
help24 DC.B ' * B.W.Mott
BSVC processor simulation famework@',0
*
********************************************************
* the startup string
*
johntxt DC.B ' Calculator program v980428c@',0
;start up string
*
********************************************************
* Have to figure out a way of displaying errors...hmmm..
*
messg1 DC.B ' Please enter a
calculation.@',0 ;the opening message
messg2 DC.B ' (0-999, and using
+,-,/,*)@',0 ;guide to symbols allowed
messg3 DC.B ' -- H=help --- C=credits
---@',0 ;the helpline
numerr DC.B ' Number must be
0-999!@',0 ;Outside of
range, shouldnt be needed
operr DC.B
' Invalid operator!@',0
;Key other than +-*/
restart DC.B ' Please re-enter
the sum. ->@',0 ;message when error occurs
addspc DC.B ' @',0
;to leave a space
diverr DC.B ' Less
than 1 @',0
;when a divide will be less than 1
again DC.B
' Press <space> to continue...@',0 ;prompt for the user
ofmessg DC.B ' Error - Overflow!@',0
;display this instead of result
*
*
********************************************************
* Now we set up all the areas of storage in memory...
*
number1 DS.W 1
;Reserve 16 bits of storage for num1
number2 DS.W 1
;Reserve 16 bits of storage for num2
op
DS.B 1
;Holds ascii val of operator
temp8 DS.B
1
;Reserve a byte for temp useage
temp16 DS.W
1
;Reserve a word for temp useage
result
DS.L 1
;A long word (32bits) to hold results
flag
DS.B 1
;whether its a -ive or not.
overflow DS.B 1
;shows whether the result of a '*' is over 16bits
*
*
*********************************************************
* Description of some things.
*
* purpose of storage
*
* name - contents - d/size - description
*
* d1 - ascii -
B - holds the character that is recieved from trap function.
* d2 - integer -
B - counter (counts to 3)
* d3 - integer -
B - used when testing whether result will be bigger than 999
* d4 - integer -
B - holds the converted form of the ascii char.
* d5 - boolean -
B - tells whether character inputted is within range.
* d6 - integer -
W - hold contents of int1+int2+int3 before adding to temp.
*
* num1 - integer1 - W -
holds upto a 3 digit integer.
* num2 - integer2 - W -
holds upto a 3 digit integer.
* op - ascii
- B - numerical operator is held here.
* tmp8 - varies -
B - a byte of scratch space.
* tmp16- varies - W
- a word of scratch space.
* res - integer - L
- final result stored here.
*
*
*********************************************************
END
$400
This code was written by J.Snowdon 1998. You are free
to use it as a resource, however, if you use any fragments of my code you
MUST acknowledge me - blatant copying will do you no good, and is against
copyright law - it's also very naughty :-) |